#include "test_runner.h"
#include "test_report.h"
#include "test.h"

namespace krryn{
namespace test{
	basic_runner::basic_runner() : m_Report(new report_null()){}

	basic_runner::~basic_runner(){
		delete m_Report;
	}

	void basic_runner::set_report(basic_report *a_Report){
		delete m_Report;
		m_Report = a_Report;
	}

	void basic_runner::add_suite(basic_test_suite &a_Suite, const std::string &a_Name){
		if(m_Suites[a_Name] != 0){
			m_Duplicates.push_back(&a_Suite);
		}else{
			m_Suites[a_Name] = &a_Suite;
		}
	}

	void basic_runner::run_all() const{
		if(!m_Duplicates.empty()){
			throw duplicate_exception(m_Duplicates);
		}

		size_t l_MaxTotal = 0;

		for(suite_list_t::const_iterator i = m_Suites.begin(); i != m_Suites.end(); i++){
			l_MaxTotal += i->second->max_tests();
		}

		m_Report->begin(l_MaxTotal);

		for(suite_list_t::const_iterator i = m_Suites.begin(); i != m_Suites.end(); i++){
			i->second->run_all(*m_Report);
		}

		m_Report->end();
	}

	init::init(){
		add();
	}

	init::~init(){
		remove();
	}

	basic_runner *init::add(){
		if(init::m_Counter++ == 0){
			// make new runner
			runner = new basic_runner();
		}

		return runner;
	}

	void init::remove(){
		if(init::m_Counter-- == 0){
			// delete runner
			delete runner;
		}
	}

	basic_runner *runner = init::add();

	size_t init::m_Counter = 0;
	static init g_Init;
}
}